home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
007
/
d86v311b.arc
/
XBIOS.8
< prev
Wrap
Text File
|
1987-09-24
|
19KB
|
541 lines
;---------------
; XBIOS test driver for BIOS.8
;---------------
; Copyright (C)1987 Eric Isaacson. All rights reserved. Permission to
; copy and use this module is granted ONLY for machines registered for both
; the A86 assembler and the D86 debugger.
; XBIOS is a program that exercises the BIOS.8 module. I am providing it
; to assist those who wish to assist me in porting my D86 debugger to
; machines with non-IBM-compatible BIOSes.
; You use this source module as follows:
;
; 1. Modify the module BIOS.8 to accommodate your specific machine. You
; should NOT need to modify this module, except possibly to add a
; new HELP-key name just before the declcaration HELP_HELP below.
;
; 2. Assemble both modules with the command A86 XBIOS.8 BIOS.8
; (Command is provided as MAKX.BAT in this package; just type MAKX.)
;
; 3. Run the resulting program XBIOS.COM. The program will run tests
; of the BIOS function calls, and tell you about them. If everything
; looks good, then your BIOS.8 probably works.
;
; 4. The XBIOS program ends with an interactive mode, displaying keystrokes.
; Please try every key on your keyboard, both with and without any
; shift-style keys (ALT, SHIFT, CTRL, SECOND, etc.). Write down the
; codes that result.
;
; 5. Send me the codes you wrote down, together with your new BIOS.8. I'll
; incorporate it into D86. Thanks!
; This is a "quick-and-dirty" program. It does not meet my standards for
; professionally-documented source code (no procedure-level comments).
JMP MAIN
ALTF10_HELP: ; HELP-key name for the IBM-PC
DB 'Alt-F10',0
F11_HELP: ; HELP-key name for the TI-PC
DB 'F11',0
PF5_HELP:
DB 'Ctrl-PF5',0
; If your machine uses a different HELP-KEY, declare its name above this line.
HELP_HELP:
DB 'HELP',0
ENABLE_PORT DW ? ; BIOS specific, used by Wang for a port number
V_FLAG DB ? ; debugger variable consulted by IBM BIOS_INIT
WAVY_COUNT DB ? ; count of how many wavy messages have been output
; DWB causes the initialization of alternating words and bytes
DWB MACRO #RX1L
DW #X
DB #AX
#E2#EM
SKIP2 MACRO ; skip over the following 2 opcode bytes
DB 03D ; CMP AX,iw opcode will do the job
#EM
SCREEN_P EQU 08000 ; screen buffer is at 08000
; The following are convenient prefix-abbreviations for returned key-codes.
CTRL EQU -040 ; e.g. CTRL'A' -- WARNING CTRL'a' will be wrong!!
FUNC EQU 59+111 ; e.g. FUNC 1 for the F1 function key
SHIFT_F EQU 84+111 ; e.g. SHIFT_F 3 for the shifted F3 key
CTRL_F EQU 94+111 ; e.g. CTRL_F 10 for the control-F10 key
ALT_F EQU 104+111 ; e.g. ALT_F 4 for the Alt-F4 key
ALT_N EQU 120+111 ; e.g. ALT_N 5 for the Alt-5 key
BIOS_CALLS: ; pointers to BIOS-specific action routines
VID_COPY DW MONO_COPY ; video copy
VID_ATTR DW IBM_ATTR ; set attribute at DI to AL
VID_FIX DW IBM_FIX ; fix video screen
BIOS_BELL DW IBM_BELL ; ring bell
BIOS_KEY DW IBM_KEY ; fetch a keystroke
BIOS_SAVE DW IBM_SAVE ; save user's BIOS state (Sanyo only)
BIOS_RESTORE DW IBM_RESTORE; restore the saved BIOS state (Sanyo only)
VIDEO_SEG DW ? ; pointer to physical video display segment
ATTR_BYTES DW ; hardware-dependent video codes
NORM_ATTR DB 7 ; code for normal video display
REV_ATTR DB 070 ; code for reversed-video display
N_BIOS_CALLS EQU ($-BIOS_CALLS)/2
BIOS_INIT DW IBM_CONFIG
; CTRL_JUMPS defines the single-key commands recognized by the debugger. Each
; DW below is an address to be jumped to whenever the following DB byte is
; taken as a single-key input by the debugger command processor.
CTRL EQU -040
CTRL_JUMPS:
DWB F1_MSG, FUNC 1
DWB F2_MSG, FUNC 2
DWB F3_MSG, FUNC 3
DWB F4_MSG, FUNC 4
DWB F5_MSG, FUNC 5
DWB F6_MSG, FUNC 6
DWB F7_MSG, FUNC 7
N_FUNCS EQU ($-CTRL_JUMPS)/3
L1: ; control-key functions start here
DWB DOWN_MSG, 80+112
DWB PGDN_MSG, 81+112
DWB UP_MSG, 72+112
DWB PGUP_MSG, 73+112
DWB HOME_MSG, 71+112
DWB SHF7_MSG, SHIFT_F 7
DWB ALTF9_MSG, ALT_F 9
N_CONTROL_KEYS EQU ($-L1)/3
DW F10_MSG
SWITCH_KEY DB FUNC 10 ; key code for FUNC 10 (switch screens)
DW HELP_HELP
HELP_KEY DB ALT_F 10 ; key code for the debugger's HELP key
DWB 0, 0FF ; terminator for this table
MAIN:
CALL SET_MACHINE ; set SUBDIR_CHAR and BIOS_INIT
CALL BIOS_INIT ; initialize our specific BIOS
MOV DS,ES,SS ; restore segment registers
CALL TEST_INIT ; display the settings produced, prompt for key
CALL TEST_KEY_BELL ; test the simple key input and bell functions
CALL TEST_VIDEO ; test some simple video displays
CALL TEST_KEY_CODES ; enter the interactive key-code display loop
MOV AX,04C00 ; MS-DOS codes for successful program exit
INT 33 ; exit back to the operating system
FIRST_TESTING:
DB 'Survived BIOS_INIT.',0D,0A
DB 'Subdirectory character is set to "'
SUBDIR_CHAR DB '\'
DB '".',0D,0A
DB 'Video memory is at segment register value '
VIDEO_DISPLAY:
DB 'xxxx.',0D,0A
DB 'The normal attribute byte is '
NORM_DISP:
DB 'xx.',0D,0A
DB 'The reverse attribute byte is '
REV_DISP:
DB 'xx.',0D,0A
DB 'The HELP key is labelled ',0
HELP_MSG DW ALTF10_HELP
POST_HELP:
DB '.',0D,0A
DB 'Is this right?',0D,0A,0D,0A
DB 'First testing BIOS key input and bell-ringing.',0D,0A,0
TEST_INIT: ; make initial display of BIOS variables
MOV BX,VIDEO_SEG ; fetch the video segment register value
MOV DI,VIDEO_DISPLAY ; point to it position in the display message
MOV AL,BH ; fetch the high byte of the value
CALL HEX_AL ; output the high byte
MOV AL,BL ; fetch the low byte of the value
CALL HEX_AL ; output the low byte
MOV DI,NORM_DISP ; point to NORM_ATTR value in message
MOV AL,NORM_ATTR ; fetch the value
CALL HEX_AL ; put the hex value into the message
MOV DI,REV_DISP ; point to REV_ATTR value in message
MOV AL,REV_ATTR ; fetch the value
CALL HEX_AL ; put the hex value into the message
MOV SI,FIRST_TESTING ; point to the first message
CALL MESSAGE ; output the message
MOV SI,HELP_MSG ; point to the name of the HELP key
CALL MESSAGE ; output the name
MOV SI,POST_HELP ; point to the message after the HELP name
JMP MESSAGE ; output the message
VID_TEST_MSG:
DB 'Now we''ll output directly to video memory.',0D,0A
DB 'Type any two keys--',0D,0A
DB 'The screen will go blank after the first keystroke.',0D,0A,0
ALPHABET_MSG:
DB 'Now letters A to X go down the left.',0
H_MSG:
DB 'Reverse video on the H.',0
AFTER_M_MSG:
DB 'Reverse video in second character beyond the M.',0
H_SPOT EQU ('H'-'A') * 160
AFTER_M_SPOT EQU ('M'-'A') * 160 + 4
TEST_VIDEO:
MOV SI,VID_TEST_MSG ; point to the "Now testing video" message
CALL MESSAGE ; output the message
CALL KEY_ONLY ; take a keystroke
CALL FIRST_FILL ; blank the screen
CALL GET_KEY ; take another keystroke
CALL ALPHA_LINES ; put out the alphabet along the side
MOV SI,ALPHABET_MSG ; point to message telling about it
CALL TOP_LINE ; output the message
CALL REFRESH ; send it all to the video
CALL GET_KEY ; take another key
MOV SI,H_MSG ; point to cursor-on-H message
CALL TOP_LINE ; output the message
CALL REFRESH ; refresh the video memory
MOV ES,VIDEO_SEG ; point to the video segment
MOV DI,H_SPOT ; point to "H" character within that segment
MOV AL,REV_ATTR ; load the reverse-attribute byte
CALL VID_ATTR ; output the byte to the video segment
MOV ES,SS ; restore ES
CALL GET_KEY ; take another keystroke
MOV SI,AFTER_M_MSG ; point to cursor-after-M message
CALL TOP_LINE ; output the message
CALL REFRESH ; refresh the video memory
MOV ES,VIDEO_SEG ; point to the video segment
MOV DI,H_SPOT ; point to the previous cursor position in segment
MOV AL,NORM_ATTR ; load normal attribute
CALL VID_ATTR ; cancel the previous cursor output
MOV DI,AFTER_M_SPOT ; point to the new cursor position
MOV AL,REV_ATTR ; load reverse-attribute byte
CALL VID_ATTR ; output the new cursor
MOV ES,SS ; restore ES
GET_KEY:
CALL BIOS_RESTORE
CALL BIOS_KEY
RET
PLEASE_TYPE:
DB 'Please type any key.',0D,0A,0
KEY_ONLY_MSG:
DB 'The BIOS returned hex code '
KEY_ONLY_HEXCODE:
DB 'xx.',0D,0A,0
KEY_ONLY:
MOV SI,PLEASE_TYPE ; point to "Please type any key"
CALL MESSAGE ; output "Please type any key"
MOV DI,KEY_ONLY_HEXCODE ; output goes to the key-value report
MOV SI,KEY_ONLY_MSG ; point to start of key-value report
CALL GET_KEY ; fetch a keystroke from the BIOS
CALL HEX_AL ; place the hex code into the message
MESSAGE: ; output null-terminated SI-message to standard out
PUSH BX,CX,DX ; save registers across call
MOV DX,SI ; MS-DOS wants the message pointer in DX
L1: ; loop here to scan for the terminator
LODSB ; fetch a string byte
TEST AL ; is it the zero terminator?
JNZ L1 ; loop if not
LEA CX,[SI-1] ; point CX to the terminator byte
SUB CX,DX ; compute the number of characters in the message
MOV AH,040 ; MS-DOS function number for WRITE
MOV BX,1 ; handle number for standard output is 1
INT 33 ; call MS-DOS to make the output
POP DX,CX,BX ; restore clobbered registers
RET
NOW_BELL:
DB 'Now we''re using BIOS to ring the bell...',0D,0A,0
HEAR_IT?:
DB 'Did you hear it?',0D,0A,0
TEST_KEY_BELL: ; take 4 test keystrokes
CALL KEY_ONLY ; take key without bell
CALL KEY_ONLY ; take second key, without bell
CALL KEY_BELL ; take a key then ring the bell
KEY_BELL: ; prompt for key, then ring the bell
CALL KEY_ONLY ; prompt for and take a keystroke
MOV SI,NOW_BELL ; point to bell message
CALL MESSAGE ; put out the bell message
CALL BIOS_BELL ; ring the bell
MOV SI,HEAR_IT? ; point to the post-bell message
JMP MESSAGE ; output the post-bell message
; REFRESH updates the console screen to the desired contents, as indicated by
; the SCRBASE buffer. The buffer is updated to show that the actual screen
; contents matches the desired contents.
REFRESH:
PUSH BX,CX,DX,BP,SI,DI,ES,DS ; preserve all registers but AX
MOV ES,VIDEO_SEG ; we will copy to the screen-segment
MOV AH,NORM_ATTR ; characters will have the normal attribute
MOV SI,SCREEN_P ; source pointer is our screen buffer
SUB DI,DI ; offset of the screen is zero
MOV BL,24 ; BL will count down lines
MOV CH,0 ; CX will always hold byte counts
L1: ; main loop for actual vs. desired comparison
MOV CL,80 ; count number of characters in a line
CALL VID_COPY ; copy this line to the video buffer
OR SI,0FF ; advance SI to the end of this buffer-page
INC SI ; bump SI to the beginning of the next page
DEC BL ; count down lines
JNZ L1 ; loop if there are more lines
POP DS,ES,DI,SI,BP,DX,CX,BX ; restore all the registers
RET
; This section of code defines the message-displays for the control keys.
MSG MACRO
#1_MSG:
DB '#1',0
#EM
MSG F1
MSG F2
MSG F3
MSG F4
MSG F5
MSG F6
MSG F7
MSG F10
MSG DOWN
MSG PGDN
MSG PGUP
MSG UP
MSG HOME
MSG SHF7
MSG ALTF9
; HEX_AL outputs to DI-pointed memory the 2-digit hex number representing
; the value of AL.
BINHEX_AL MACRO
ADD AL,090H ; these 4 lines convert AL into an ASCII hex digit,
DAA ; in an outrageously clever and incomprehensible
ADC AL,040H ; fashion!!! (I got the 8080 version of this out
DAA ; of an early BYTE magazine.)
#EM
HEX_AL:
AAM 16 ; unpack AL into nibbles AH and AL
CALL >L3 ; swap nibbles, then output new low nibble
L3: ; call here to output nibble AH
XCHG AL,AH ; swap the nibble into AL
BINHEX_AL ; convert AL to a hex digit
STOSB ; output the digit
RET
FIRST_FILL: ; fill the video screen with its first contents
MOV DI,SCREEN_P ; point to our screen image
MOV CX,(24 BY 0)/2 ; load the number of words in the image buffer
SUB AX,AX ; we will zero-fill the buffer
REP STOSW ; buffer is initialized to all-zeroes
MOV AL,' ' ; now load a blank
CALL FILL_LINES ; fill the character line-buffers with blanks
CALL VID_FIX ; insure that this first screen was actually sent
CALL REFRESH ; send our screen buffer to video memory
RET
ALPHA_LINES: ; put alphabet A to X down the left side
MOV DI,SCREEN_P ; point to the upper left corner
MOV CX,24 ; load the lines count
MOV AL,'A' ; load the first letter
L1: ; loop here to output each letter
STOSB ; output the letter
INC AX ; increment to the next letter
ADD DI,255 ; advance output pointer to the next line
LOOP L1 ; loop to output the next letter
RET
FILL_LINES: ; fill all 24 image-lines with AL
MOV DI,SCREEN_P ; point to the start of the image-buffer
MOV BL,24 ; number of lines in the buffer
L1: ; loop here for each line
CALL FILL_LINE ; fill the line with AL
DEC BL ; count down lines
JNZ L1 ; loop to fill the next line
RET
FILL_LINE: ; fill the DI-pointed line with AL, advance DI
MOV CX,80 ; number of characters in the line
REP STOSB ; fill the line
ADD DI,256-80 ; advance output pointer to the next line buffer
RET
PRESS_KEY:
DB ' Press any key',0
TOP_LINE: ; put SI-message and "press key" on top line
MOV DI,SCREEN_P+3 ; point to the fourth character of the top line
CALL COPY_STRING ; output the caller's SI-pointed message
MOV SI,PRESS_KEY ; now point to our "press key" message
COPY_LINE:
CALL COPY_STRING ; output the "press key" message
MOV CX,DI ; copy the beyond-output pointer to CX
MOV CL,80 ; advance the pointer to the end of the top line
SUB CX,DI ; calculate the number of trailing bytes in the line
MOV AL,' ' ; load blank
REP STOSB ; blank-fill the trailing bytes
RET
ALL_KEYS:
DB 'Now try out all possible keystrokes.',0
CAP_Q:
DB 'Capital Q exits program; capital T trashes the screen.',0
TRASH_MESSAGE:
DB 'The message is output via MS_DOS.',0D,0A
DB 'It will roll the screen, thereby trashing the display.',0D,0A
DB 'Type capital-F to fix the screen if it is trashed.',0D,0A,0
KNOWN_MSG:
DB 'I recognize that function key, its name is '
KNOWN_TAIL:
DB ' ',0
UNKNOWN_MSG:
DB 'That key code is not in my table. Its value is '
UNKNOWN_HEXCODE:
DB 'xx',0
DISPLAYING_MSG:
DB 'Displayable character was typed: the character is "'
DISPLAYING_CHAR DB 'x"',0
TEST_KEY_CODES: ; interactive routine for displaying key codes
MOV SI,ALL_KEYS ; point to the main prompting message
MOV DI,SCREEN_P+3 ; point to the location in our buffer for message
CALL COPY_LINE ; output the first line of the message
MOV SI,CAP_Q ; point to second line of message
MOV DI,SCREEN_P+0103 ; point to location in buffer for that message
CALL COPY_LINE ; output the second line
L1: ; loop here for each keystroke
CALL REFRESH ; refresh the video screen
CALL GET_KEY ; take a keystroke
CMP AL,'Q' ; is it the exiting capital-Q?
JE RET ; if yes then exit
CMP AL,'T' ; is it the TRASH command?
JE >L6 ; jump if yes
CMP AL,'F' ; is it the FIX command?
JE >L7 ; jump if yes
MOV BL,AL ; copy character to BL for WAVY-function
CMP AL,' ' ; is the character a control character?
JB >L5 ; jump if yes
CMP AL,07E ; is the character above the displaying range?
JA >L5 ; jump if yes
MOV DISPLAYING_CHAR,AL ; character is displayable-- put it into message
MOV SI,DISPLAYING_MSG ; point to the displayable message
JMP >L4 ; jump to propagate the message
L5: ; keystroke is not a displayable character
MOV DI,CTRL_JUMPS+2 ; point to our table of function keys
L2: ; loop here to search each entry of function table
CMP B[DI],0FF ; is the table exhausted?
JE >L3 ; jump if yes, key not in table
SCASB ; does our key match the table entry?
LEA DI,[DI+2] ; advance table pointer in case not
JNE L2 ; loop if not
MOV SI,[DI-5] ; the key matches-- fetch the pointer from that record
MOV DI,KNOWN_TAIL ; point to the end of the known-message
CALL COPY_STRING ; tack the key's name onto the known-message
MOV AL,0 ; load terminator
STOSB ; null-terminate the known-message
MOV SI,KNOWN_MSG ; point to the start of the known-message
JMP >L4 ; jump to propagate the message
L3: ; keystroke was not found in the function table
MOV DI,UNKNOWN_HEXCODE ; point to hex-display part of unknown-message
CALL HEX_AL ; output our keycode as hex digits
MOV SI,UNKNOWN_MSG ; point to the start of the unknown message
L4: ; common output point
CALL WAVY_MESSAGES ; output the SI-pointed message in a wavy display
JMP L1 ; loop to take another keystroke
L6: ; capital T is seen
MOV SI,TRASH_MESSAGE ; point to our message that trashes the screen
CALL MESSAGE ; trash the screen with the message
CALL BIOS_SAVE
JMP L1 ; loop to take another keystroke
L7: ; capital F is seen
CALL VID_FIX ; fix up the trashed screen
JMP L1 ; loop to take another keystroke
COPY_STRING: ; copy SI-pointed string to DI
LODSB ; load the first character
L1: ; loop here for each nonzero character
STOSB ; output the character
LODSB ; fetch the next character
TEST AL ; is it the terminating zero?
JNZ L1 ; loop if not
RET
WAVY DB 3,4,5,6,7,6,5,4
WAVY_MESSAGES: ; make 20 copies of SI-message in a wavy pattern
INC WAVY_COUNT ; increment display count
MOV DI,SCREEN_P+0404 ; point to the first line of the wavy display
MOV BH,20 ; load the count of lines to be output
L1: ; loop here to output each line
MOV CX,DI ; fetch the output pointer
MOV CL,CH ; low byte tells us a reltive line number
ADD CL,BL ; add in character code, just to mix things up
SUB CL,WAVY_COUNT ; now a repeat of same key will make waves
AND CX,7 ; waviness will have a period of 8 lines
XCHG BX,CX ; swap the line-index into BX, for addressing
MOV BL,WAVY[BX] ; translate line-index into an indetation count
XCHG CX,BX ; swap the count back into CX
MOV AL,' ' ; load blank
REP STOSB ; indent the message-- this creates the waviness
PUSH SI ; save the message pointer for the next line
CALL COPY_LINE ; copy the message to this line, with trailing blanks
POP SI ; restore the message pointer
ADD DI,260-80 ; advance output to the next line
DEC BH ; count down lines
JNZ L1 ; loop to output the next line
RET